﻿namespace EFS.RC.CC.Applications.EndPoints.OfficeService
{
	/// <summary>
	/// DirectDial End Point
	/// </summary>
	internal class DirectDial : EFS.RC.CC.Applications.EndPoints.Presence<EFS.RC.CC.Config.DirectDialDeployment, EFS.RC.CC.Presences.EndPoints.OfficeService.DirectDial>
	{
		#region Composition

		#endregion

		#region Constructor

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="ownerUri"></param>
		public DirectDial(
			Microsoft.Rtc.Collaboration.ApplicationEndpointSettings applicationEndpointSettings,
			EFS.RC.CC.Presences.EndPoints.OfficeService.DirectDial directDialEndPointPresence)
			: base(applicationEndpointSettings, directDialEndPointPresence)
		{
			// distribution
			EFS.Common.Verify.Reference(applicationEndpointSettings, "applicationEndpointSettings");
		}

		#endregion

		#region Usage

		/// <summary>
		/// Describe this object
		/// </summary>
		/// <returns></returns>
		public override System.String Describe()
		{
			return System.String.Format("EFS.RC.CC.Applications.EndPoints.OfficeService.DirectDial [{0}]", base.Describe());
		}

		/// <summary>
		/// Agents end point
		/// </summary>
		public EFS.RC.CC.Applications.EndPoints.OfficeService.Operators OfficeServiceOperatorsEndPointApplication
		{
			get
			{
				// presence knows operators presence as well
				return ApplicationPresence.EndPointsPresencesRegistrar.OperatorOfficeServiceEndPointPresence.PresenceEndPointApplication;
			}
		}

		/// <summary>
		/// Deployment reload
		/// </summary>
		/// <returns></returns>
		public void ReloadDeployment()
		{
		}

		#endregion

		#region Startup

		/// <summary>
		/// End point active
		/// </summary>
		protected override void PostEndPointEstablish(Microsoft.Rtc.Collaboration.ApplicationEndpoint collaborationApplicationEndpoint)
		{
			// log
			EFS.EventLog.Log.LogInfo("PostEndPointEstablish", this);

			// check
			EFS.Common.Verify.Reference(collaborationApplicationEndpoint, "collaborationApplicationEndpoint");

			// register for audio/video calls
			collaborationApplicationEndpoint.RegisterForIncomingCall<Microsoft.Rtc.Collaboration.AudioVideo.AudioVideoCall>(OnIncomingAudioVideoCallCalls);
			collaborationApplicationEndpoint.RegisterForIncomingCall<Microsoft.Rtc.Collaboration.InstantMessagingCall>(OnIncomingInstantMessagingCalls);
		}

		#endregion

		#region Runtime

		/// <summary>
		/// Incomming messages
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="args"></param>
		private void OnIncomingInstantMessagingCalls(object sender, Microsoft.Rtc.Collaboration.CallReceivedEventArgs<Microsoft.Rtc.Collaboration.InstantMessagingCall> args)
		{
			// log
			EFS.EventLog.Log.LogInfo(System.String.Format("OnIncomingInstantMessagingCalls {0}", args.RemoteParticipant.Uri), this);

			try
			{
				// SAL
				EFS.RC.CC.Tools.Loggers.SAL.Add(null, "OnIncomingInstantMessagingCalls", args.RemoteParticipant.Uri, this);

				// decline
				args.Call.Decline();
			}
			catch (System.Exception ex)
			{
				// handle ex
				EFS.EventLog.Log.LogException(ex, this);
			}
		}

		/// <summary>
		/// On incomming audio-video calls
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="args"></param>
		private void OnIncomingAudioVideoCallCalls(object sender, Microsoft.Rtc.Collaboration.CallReceivedEventArgs<Microsoft.Rtc.Collaboration.AudioVideo.AudioVideoCall> args)
		{
			// log
			EFS.EventLog.Log.LogInfo(System.String.Format("OnIncomingAudioVideoCallCalls {0}", args.RemoteParticipant.Uri), this);

			try
			{
				// SAL
				EFS.RC.CC.Tools.Loggers.SAL.Add(null, "OnIncomingAudioVideoCallCalls", args.Call.RemoteEndpoint.Participant.DisplayName, this);

				// Must be new call (agent)
				if (args.IsNewConversation && args.CallToBeReplaced == null)
				{
					// get customer end point used by directDials
					EFS.RC.CC.Presences.EndPoints.OfficeService.Customer customerOfficeServiceEndPointPresence =
							ApplicationPresence.EndPointsPresencesRegistrar.GetGatewayCustomerOfficeServicePresence();

					// check
					if (null != customerOfficeServiceEndPointPresence)
					{
						// check DDI
						if (IsDDICall(args.RequestData.FromHeader.Uri.ToLower()))
						{
							// make a presence with participant name from gate call
							EFS.RC.CC.Presences.Operators.Presence presence = new EFS.RC.CC.Presences.Operators.Anonymous(args.RequestData.ToHeader.Uri);

							// log
							EFS.EventLog.Log.LogInfo(System.String.Format("Direct Dial In for {0} from {1}", args.RequestData.ToHeader.Uri, args.Call.RemoteEndpoint.Participant.Uri), this);

							// direct customer session
							EFS.RC.CC.Sessions.OfficeService.Customers.DirectDialIn customerSession = new EFS.RC.CC.Sessions.OfficeService.Customers.DirectDialIn(
								customerOfficeServiceEndPointPresence.PresenceEndPointApplication, args.Call, presence, args.RequestData.FromHeader.Uri);

							// start
							customerSession.BeginStartup();
						}
						else // DO
						{
							// make a presence with participant name from gate call
							EFS.RC.CC.Presences.Operators.Presence presence = new EFS.RC.CC.Presences.Operators.Anonymous(args.RequestData.FromHeader.Uri);

							// log
							EFS.EventLog.Log.LogInfo(System.String.Format("Dial Out from {0} to {1}", args.Call.RemoteEndpoint.Participant.Uri, args.RequestData.ToHeader.Uri), this);

							// make a dialout session
							EFS.RC.CC.Sessions.OfficeService.Operators.DialOut operatorSession = new EFS.RC.CC.Sessions.OfficeService.Operators.DialOut(
								presence,
								customerOfficeServiceEndPointPresence.PresenceEndPointApplication,
								args.Call,
								args.RequestData.FromHeader,
								args.RequestData.ToHeader);

							// start agent session
							operatorSession.BeginStartup();
						}
					}
					else
					{
						// decline
						args.Call.Decline();
					}
				}
				// Must be new call (customer)
				else if (!args.IsNewConversation && args.CallToBeReplaced != null)
				{
					// log
					EFS.EventLog.Log.LogInfo(System.String.Format("OnIncomingAudioVideoCallCalls New Conversation with Replace {0}", args.RemoteParticipant.Uri), this);

					// check if call is dial out
					if (args.CallToBeReplaced.Conversation.ApplicationContext is EFS.RC.CC.Sessions.OfficeService.Operators.DialOut)
					{
						// pass the call to session
						(args.CallToBeReplaced.Conversation.ApplicationContext as EFS.RC.CC.Sessions.OfficeService.Operators.DialOut).HandleReplacedCall(args.Call);
					}
					else
					{
						// log
						EFS.EventLog.Log.LogInfo(System.String.Format("OnIncomingAudioVideoCallCalls Call not handled {0}", args.RemoteParticipant.Uri), this);

						// decline call
						args.Call.Decline();
					}
				}
				else
				{
					// decline
					args.Call.Decline();
				}
			}
			catch (System.Exception ex)
			{
				// log
				EFS.EventLog.Log.LogException(ex, this);

				try
				{
					// decline call
					args.Call.Decline();
				}
				catch (System.Exception ex1)
				{
					// log
					EFS.EventLog.Log.LogException(ex1, this);
				}
			}
		}

		/// <summary>
		/// Check if call is DDI
		/// </summary>
		/// <param name="uri"></param>
		/// <returns></returns>
		private System.Boolean IsDDICall(System.String uri)
		{ 
			// check
			EFS.Common.Verify.String(uri, "uri");

			// check DDI phone context
			if (uri.IndexOf(EFS.RC.CC.Config.Settings.DirectDialPhoneContext, System.StringComparison.InvariantCultureIgnoreCase) >= 0)
			{
				return true;
			}

			// check annonimous caller
			if (uri.IndexOf(EFS.RC.CC.Config.Settings.AnonymousPhone, System.StringComparison.InvariantCultureIgnoreCase) >= 0)
			{
				return true;
			}

			// not ddi
			return false;
		}

		#endregion

		#region Shutdown

		/// <summary>
		/// Clean-up 
		/// </summary>
		/// <param name="collaborationApplicationEndpoint"></param>
		protected override void PreEndPointTerminate(Microsoft.Rtc.Collaboration.ApplicationEndpoint collaborationApplicationEndpoint)
		{
			// log
			EFS.EventLog.Log.LogInfo("PreEndPointTerminate", this);

			// check
			EFS.Common.Verify.Reference(collaborationApplicationEndpoint, "collaborationApplicationEndpoint");

			//unregister the events
			collaborationApplicationEndpoint.UnregisterForIncomingCall<Microsoft.Rtc.Collaboration.AudioVideo.AudioVideoCall>(OnIncomingAudioVideoCallCalls);
			collaborationApplicationEndpoint.UnregisterForIncomingCall<Microsoft.Rtc.Collaboration.InstantMessagingCall>(OnIncomingInstantMessagingCalls);
		}

		/// <summary>
		/// Stopped 
		/// </summary>
		/// <param name="collaborationApplicationEndpoint"></param>
		protected override void EndPointStopped()
		{
			// log
			EFS.EventLog.Log.LogInfo("EndPointStopped", this);
		}

		#endregion
	}
}
